/**
 * 批量写入服务
 * 用于优化高频数据库写入操作，减少数据库负载
 */

const db = require('../config/database');
const logger = require('../config/logger');

class BatchWriteService {
  constructor() {
    // 传输进度缓冲区
    this.transferProgressBuffer = new Map();
    
    // 日志缓冲区
    this.logBuffer = [];
    
    // 统计数据缓冲区
    this.statsBuffer = new Map();
    
    // 配置
    this.config = {
      // 批量大小
      transferBatchSize: 50,
      logBatchSize: 100,
      statsBatchSize: 30,
      
      // 刷新间隔（毫秒）
      transferFlushInterval: 4000,  // 4秒 - 传输记录和流量
      logFlushInterval: 10000,       // 10秒
      statsFlushInterval: 4000      // 4秒 - 网络流量统计
    };
    
    // 启动定时刷新
    this.startAutoFlush();
  }
  
  /**
   * 添加传输进度更新到缓冲区
   */
  addTransferProgress(taskId, data) {
    this.transferProgressBuffer.set(taskId, {
      taskId,
      ...data,
      updatedAt: new Date()
    });
    
    // 如果达到批量大小，立即刷新
    if (this.transferProgressBuffer.size >= this.config.transferBatchSize) {
      this.flushTransferProgress();
    }
  }
  
  /**
   * 添加日志到缓冲区
   */
  addLog(logData) {
    this.logBuffer.push({
      ...logData,
      createdAt: new Date()
    });
    
    // 如果达到批量大小，立即刷新
    if (this.logBuffer.length >= this.config.logBatchSize) {
      this.flushLogs();
    }
  }
  
  /**
   * 添加统计数据到缓冲区
   */
  addStats(key, data) {
    this.statsBuffer.set(key, {
      key,
      ...data,
      updatedAt: new Date()
    });
    
    // 如果达到批量大小，立即刷新
    if (this.statsBuffer.size >= this.config.statsBatchSize) {
      this.flushStats();
    }
  }
  
  /**
   * 批量刷新传输进度
   */
  async flushTransferProgress() {
    if (this.transferProgressBuffer.size === 0) return;
    
    const records = Array.from(this.transferProgressBuffer.values());
    this.transferProgressBuffer.clear();
    
    try {
      // 构建批量更新SQL
      const cases = [];
      const taskIds = [];
      
      records.forEach(record => {
        taskIds.push(record.taskId);
        
        if (record.progress !== undefined) {
          cases.push(`WHEN ${db.escape(record.taskId)} THEN ${db.escape(record.progress)}`);
        }
      });
      
      if (cases.length > 0) {
        const sql = `
          UPDATE transfer_tasks
          SET 
            transferred_bytes = CASE id ${cases.join(' ')} ELSE transferred_bytes END,
            transfer_speed = CASE id ${
              records.map(r => r.speed !== undefined ? 
                `WHEN ${db.escape(r.taskId)} THEN ${db.escape(r.speed)}` : ''
              ).filter(Boolean).join(' ')
            } ELSE transfer_speed END,
            updated_at = NOW()
          WHERE id IN (${taskIds.map(id => db.escape(id)).join(',')})
        `;
        
        await db.query(sql);
        logger.info(`批量刷新传输进度: ${records.length}条记录`);
      }
    } catch (error) {
      logger.error('批量刷新传输进度失败:', error);
      // 失败时重新加入缓冲区
      records.forEach(record => {
        this.transferProgressBuffer.set(record.taskId, record);
      });
    }
  }
  
  /**
   * 批量刷新日志
   */
  async flushLogs() {
    if (this.logBuffer.length === 0) return;
    
    const logs = [...this.logBuffer];
    this.logBuffer = [];
    
    try {
      const values = logs.map(log => [
        log.userId || null,
        log.userType || 'system',
        log.action,
        log.module || 'system',
        log.content,
        log.ipAddress || null,
        log.userAgent || null,
        log.level || 'info',
        log.createdAt
      ]);
      
      if (values.length > 0) {
        await db.query(
          `INSERT INTO system_logs 
          (user_id, user_type, action, module, content, ip_address, user_agent, level, created_at) 
          VALUES ?`,
          [values]
        );
        
        logger.info(`批量刷新日志: ${logs.length}条记录`);
      }
    } catch (error) {
      logger.error('批量刷新日志失败:', error);
      // 失败时重新加入缓冲区
      this.logBuffer.push(...logs);
    }
  }
  
  /**
   * 批量刷新统计数据
   */
  async flushStats() {
    if (this.statsBuffer.size === 0) return;
    
    const stats = Array.from(this.statsBuffer.values());
    this.statsBuffer.clear();
    
    try {
      const values = stats.map(stat => [
        stat.statDate || new Date().toISOString().split('T')[0],
        stat.statHour || new Date().getHours(),
        stat.totalUpload || 0,
        stat.totalDownload || 0,
        stat.uploadCount || 0,
        stat.downloadCount || 0,
        stat.activeUsers || 0,
        stat.avgCpuUsage || 0,
        stat.avgMemoryUsage || 0,
        stat.avgDiskUsage || 0
      ]);
      
      if (values.length > 0) {
        await db.query(
          `INSERT INTO system_stats 
          (stat_date, stat_hour, total_upload, total_download, upload_count, download_count, 
           active_users, avg_cpu_usage, avg_memory_usage, avg_disk_usage) 
          VALUES ?
          ON DUPLICATE KEY UPDATE
            total_upload = VALUES(total_upload),
            total_download = VALUES(total_download),
            upload_count = VALUES(upload_count),
            download_count = VALUES(download_count),
            active_users = VALUES(active_users),
            avg_cpu_usage = VALUES(avg_cpu_usage),
            avg_memory_usage = VALUES(avg_memory_usage),
            avg_disk_usage = VALUES(avg_disk_usage)`,
          [values]
        );
        
        logger.info(`批量刷新统计数据: ${stats.length}条记录`);
      }
    } catch (error) {
      logger.error('批量刷新统计数据失败:', error);
      // 失败时重新加入缓冲区
      stats.forEach(stat => {
        this.statsBuffer.set(stat.key, stat);
      });
    }
  }
  
  /**
   * 启动自动刷新定时器
   */
  startAutoFlush() {
    // 传输进度自动刷新
    setInterval(() => {
      this.flushTransferProgress();
    }, this.config.transferFlushInterval);
    
    // 日志自动刷新
    setInterval(() => {
      this.flushLogs();
    }, this.config.logFlushInterval);
    
    // 统计数据自动刷新
    setInterval(() => {
      this.flushStats();
    }, this.config.statsFlushInterval);
    
    logger.info('批量写入服务已启动');
  }
  
  /**
   * 手动刷新所有缓冲区
   */
  async flushAll() {
    await Promise.all([
      this.flushTransferProgress(),
      this.flushLogs(),
      this.flushStats()
    ]);
  }
  
  /**
   * 获取缓冲区状态
   */
  getBufferStatus() {
    return {
      transferProgress: this.transferProgressBuffer.size,
      logs: this.logBuffer.length,
      stats: this.statsBuffer.size
    };
  }
}

// 创建单例
const batchWriteService = new BatchWriteService();

module.exports = batchWriteService;

